package com.tgy.MyFlowable.workflow.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.ctsi.core.common.util.$;
import com.ctsi.core.common.util.SecurityUtil;
import com.ctsi.workflow.service.IFlwCommonService;
import com.ctsi.workflow.service.IFlwDefinitionService;
import com.ctsi.workflow.service.IFlwOptionService;
import com.ctsi.workflow.service.IFlwStartProcessService;
import com.google.gson.Gson;
import lombok.RequiredArgsConstructor;
import org.flowable.engine.FormService;
import org.flowable.engine.IdentityService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 流程发起业务接口实现类
 *
 * @version 1.0
 * @author: wang xiao xiang
 * @date: 2021/8/20 8:40
 */
@Service
@RequiredArgsConstructor
public class FlwStartProcessServiceImpl implements IFlwStartProcessService {

    private final IdentityService identityService;
    private final IFlwDefinitionService flwDefinitionService;
    private final IFlwOptionService flwOptionService;
    private final RuntimeService runtimeService;
    private final TaskService taskService;
    private final IFlwCommonService flwCommonService;
    /**
     * 使用此方式解决formService重名问题
     **/
    private final FormService formService;

    @Autowired
    private HttpServletRequest request;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void start(String processDefinitionId, Map<String, String> variables, String nextAssignee, String nextDueDate, Integer nextPriority) {
        //获取流程定义，同时校验了流程定义是否存在以及是否挂起
        ProcessDefinition processDefinition = flwDefinitionService.queryProcessDefinitionWithValidStatus(processDefinitionId);
        if ($.isEmpty(variables)) {
            variables = CollectionUtil.newHashMap();
        }
        processDefinitionId = processDefinition.getId();
        //设置启动人id，很重要，当在流程设计器设置节点办理人为任务发起人时，所需参数为${INITIATOR}，即在此处设置的人
        //identityService.setAuthenticatedUserId($.toStr(MarsContextHolder.getUserId()));
        identityService.setAuthenticatedUserId($.toStr(SecurityUtil.getUsername(request).getId()));
        String formData = variables.get("formData");
        Gson gson = new Gson();
        Map<String, Object> map = new HashMap<String, Object>();
        map = gson.fromJson(formData, map.getClass());
        Map<String, String> newMap = map.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, e -> String.valueOf(e.getValue())));
        //启动，将启动参数传入表单

        newMap.put("INITIATOR", $.toStr(SecurityUtil.getUsername(request).getId()));
        ProcessInstance processInstance = formService.submitStartFormData(processDefinitionId, newMap);
        //获取流程实例id
        String processInstanceId = processInstance.getId();
        //设置流程标题
        String processTitle = flwOptionService.getTitleByProcessDefinitionId(processDefinitionId);
        if ($.isNotEmpty(processTitle)) {
            runtimeService.setProcessInstanceName(processInstanceId, processTitle);
        }
        //如果该流程设置了自动完成第一个任务则自动完成
        boolean jumpFirst = flwOptionService.getFlowableOptionJumpFirst(processDefinitionId);
        if (jumpFirst) {
            final Map<String, Object> vars = map;
            //获取当前任务，注意，当该节点为多实例，如并行审批的时候，任务可能有多个,查询任务列表，并都自动完成
            List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
            if ($.isNotEmpty(taskList)) {
                if (CollectionUtil.isNotEmpty(vars)) {
                    taskList.forEach(task -> flwCommonService.complete(task.getId(), vars));
                } else {
                    taskList.forEach(task -> flwCommonService.complete(task.getId()));
                }
            }
        }
        //如果该流程设置了跳过相同处理人则自动完成
        boolean smartComplete = flwOptionService.getFlowableOptionSmartComplete(processDefinitionId);
        if (smartComplete) {
            flwCommonService.smartCompleteNext(processInstanceId);
        }
        //如果设定了下一任务审批人，则设置该审批人
        if ($.isNotEmpty(nextAssignee)) {
            flwCommonService.setNextAssignee(processInstanceId, nextAssignee);
        }

        //如果设定了下一任务审批期限，则设置审批期限
        if ($.isNotEmpty(nextDueDate)) {
            flwCommonService.setNextDueDate(processInstanceId, nextDueDate);
        }

        //如果设定了下一任务审批优先级，则设置审批优先级
        if ($.isNotEmpty(nextPriority)) {
            flwCommonService.setNextPriority(processInstanceId, nextPriority);
        }
    }
}
